#ifndef YIGNETWORKCHANNEL_H
#define YIGNETWORKCHANNEL_H

// System includes
#include <QHash>
#include <QObject>
#include <QPoint>

// Local includes
#include "interface/yigsynth.h"
#include "interface/yigcable.h"
#include "graphics/yigcablegraphic.h"
//#include "sc++/sclang.h"
#include "sc++/bus.h"
//#include "sc++/group.h"
//#include "yig.h"

class Yig;

/**
*   YigNetworkChannel definines the seperate spaces for users to work in independantly or as a group.
*/
class YigNetworkChannel : public QObject
{
    Q_OBJECT

public:

    /**
    *   YigNetworkChannel Constructor
    *   @param int  Id Number for this channel
    *   @param Yig* yig pointer to the current instance of the main Yig class
    */
    YigNetworkChannel(int channelID, Yig* yig);

    /**
    *   YigNetworkChannel Deconstructor
    */
    ~YigNetworkChannel();

    /**
    *   Get the id of this channel instance
    *   @return int The ChannelID
    */
    int getChannelID();

    /**
    *   getSynthMap returns the synthMap!
    *   @return QHash<QString, YigSynth*> The map of string keys and synths
    */
    QHash<QString, YigSynth*> getSynthMap();

signals:

    /**
    *   synthCreated emitted when something has created a new synth in the network or locally
    *   @param YigSynth* pointer to the yigSynth that was created
    *   @param QString the map key of the new synth object
    *   @param QString the synthName of the new object
    *   @param QPoint the location of the new object
    *   @param float the randomized first parameter
    *   @param float the randomized second parameter
    */
    void synthCreated(YigSynth* yigSynth, QString mapKey, QString synthName, QPoint point, float param1, float param2);

    /**
    *   synthDestroyed emitted when a synth has been destroyed in the network or locally
    *   @param QString the map key of the deleted synth object
    */
    void synthDestroyed(QString);

public slots:

    /** creates the synthGroup and cableGroup nodes on the sc synth server */
    void createGroups();

    /**
    *   requestCreateSynth Called after drag/drop in the gui to request the server to create a synth
    *   @param QString userName Name of the user who created the synth, used for the mapKey generation
    *   @param QPoint point Where the synth is being created in the gui.
    *   @param QString synthName name of the synth type used to create the object.
    *   @param float the randomized first parameter
    *   @param float the randomized second parameter
    */
    void requestCreateSynth(QString userName, QString synthName, QPoint point, float param1, float param2);

    /**
    *   createSynthObject Called after drag/drop in the gui
    *   @param QString Key map key for the new synth WILL BE KEY IN THE FUTURE
    *   @param QPoint point Where the synth is being created in the gui.
    *   @param QString synthName name of the synth type used to create the object.
    *   @param float the randomized first parameter
    *   @param float the randomized second parameter
    */
    void createSynthObject(QString key, QString synthName, QPoint point, float param1, float param2);

    /**
    *   requestDestroySynth Request from server to delete a synth from the gui, removing it from the necessary maps and deleting it
    *   @param QString key The map key for the synth object, so we can correctly identify it
    */
    void requestDestroySynth(QString key);

    /**
    *   destroySynthObject Delete a synth from the gui, removing it from the necessary maps and deleting it
    *   @param QString key The map key for the synth object, so we can correctly identify it
    */
    void destroySynthObject(QString key);

    /**
    *   updates a synth parameter modulation from the network
    *   @param const char* The map key for the synth
    *   @param float the new value of the parameter
    */
    void updateSynthParam1(QString mapKey, float param1);

    /**
    *   updates a synth parameter modulation from the network
    *   @param const char* The map key for the synth
    *   @param float the new value of the parameter
    */
    void updateSynthParam2(QString mapKey, float param2);

    /**
    *   called when a a set synth name messages comes over the network, however we use it to check if a synth is in our map
    *   @param QString the map key for the synth
    *   @param QString the synth name.
    */
    void checkSynthAlive(QString mapKey, QString synthName);

    /**
    *   createCableObject slot called when the user has created a new cable between two synths
    *   @param QString mapKey The network channel view map key for this cable
    *   @param QString inputKey the map key for the synth that BEGINS the cable
    *   @param CableOutputType outputKey the map key for the synth that ENDS the cable
    *   @param QString outputType the type of output for the cable, either NO_OUTPUT, AUDIO, or MODULATION
    */
    void createCableObject(QString mapKey, QString inputKey, QString outputKey, YigCableGraphic::CableOutputType outputType);

    /**
    *   destroyCableObject slot called when the user has deleted a cable, directly or indirectly
    *   @param QString mapKey The network channel view map key for this cable
    */
    void destroyCableObject(QString mapKey);

private:

    /** id of this channel instance */
    int mChannelID;
    /** Map of Synths in this network channel */
    QHash<QString,YigSynth*> synthMap;
    /** Map of Cables in this network channel */
    QHash<QString,YigCable*> cableMap;
    /** counter to keep synth map keys unique */
    int synthCounter;
    /** pointer to the current instance of the main Yig class */
    Yig* mYig;
    /** bus reserve allows us to aquire unique buses from sc synth */
    Bus busReserve;
    /** groups for organzing synth node order in sc synth */
    sc::Group* synthGroup;
    /** groups for organzing cable node order in sc synth */
    sc::Group* cableGroup;
    /** This is a hacky patch for the drag/drop triggering multiple times */
    QPoint lastPoint;
};

#endif // YIGNETWORKCHANNEL_H
